package sostats.core.query;

import java.sql.ResultSet;
import java.sql.SQLException;

import sostats.core.base.StatisticalContext;
import sostats.core.help.SostatsException;
import sostats.core.help.Tuple;


public class QueryExecutor {
	private static SqlContext generateSubClause(Query query,StatisticalContext context) throws SostatsException{
		SqlContext sqlContext = new SqlContext();
		String distinctTable = query.getSummary().split(StatisticalContext.CONNECTOR)[0];
		String pk = context.getDistinctKey(distinctTable);
		Select select= sqlContext.select();
		if(pk!=null) select.column(" distinct "+pk+" as distinck_m ");
		select.column(query.getSummary());
		for(String column:query.getCategories()){
			select.column(column);
		}
		From from = select.from().table(query.fromTable(context));
		Join join=null;
		if(query.isMultitable()) {
			for(Tuple<String,String> joining:query.joinTables(context)){
				join = from.join();
				join.table(joining.getFirst(), joining.getSecond());
			}
		}
		if(query.whereConditions().size()>0){
			Where where = null;
			for(ConditionBuilder cb:query.whereConditions()){
				String column = cb.getAttribute();
				for(String condition:cb.build(query.getParameters(column))){
					if(where==null) where = join!=null?join.where():from.where();
					where.and(condition);
				}
			}
			if(where!=null) {
				where.end();
			}else{
				join.end();
			}
		}
		return sqlContext;
	}
	private static String getPureColumn(String column){
		return column.split(StatisticalContext.CONNECTOR)[1];
	}
	public static Dataset doQuery(
			Query query, StatisticalContext context) throws SQLException, SostatsException{
		SqlContext sqlContext = new SqlContext();
		Select select = sqlContext.select();
		select.column(query.getSummaryType().operate(getPureColumn(query.getSummary())));
		for(String column:query.getCategories()){
			select.column(getPureColumn(column));
		}
		From from = select.from().subClause(generateSubClause(query,context));
		GroupBy groupBy = from.groupBy();
		for(String column:query.groupByColumns()){
			groupBy.column(getPureColumn(column));
		}
		groupBy.end();
		ResultSet rs = sqlContext.execute(context.getConnection());
		return parseResult(rs,query);
	}
	private static Dataset  parseResult(ResultSet rs, Query query) throws SQLException, SostatsException{
		int dimension = query.dimension();
		Dataset dataset = new Dataset(dimension);
		while(rs.next()){
			Object value = rs.getObject(1);
			Object[] data = new Object[dimension];
			for(int i=0;i<dimension;i++){
				data[i]=rs.getObject(i+2);
			}
			dataset.addData(value, data);
		}
		return dataset;
	}
}
